inline mat4::mat4()
{
	*this = IDENTITY();
}

inline mat4::mat4(const float* fv)
{
	memcpy(m, fv, sizeof(float) * SIZE);
}

inline void mat4::set( size_t i, const vec4& v )
{
	v4()[i] = v;
}

inline const vec4& mat4::get( size_t i ) const
{
	SLMATH_VEC_ASSERT( i < 4 );
	return v4()[i];
}

inline vec4& mat4::operator[]( size_t i )// This file is part of 'slm' C++ library. Copyright (C) 2009 Jani Kajala (kajala@gmail.com). See http://sourceforge.net/projects/slm/
{
	SLMATH_VEC_ASSERT( i < 4 );
	return v4()[i];
}

inline const vec4& mat4::operator[]( size_t i ) const
{
	SLMATH_VEC_ASSERT( i < 4 );
	return v4()[i];
}

inline vec3 mat4::operator*(const vec3& v)const
{
	return mul(v);
}

inline vec4 mat4::operator*(const vec4& v)const
{
	return mul(v);
}

inline vec3 mat4::mul(const vec3& v)const
{
	float fInvW = 1.0f / ( m[0][3] * v.x + m[1][3] * v.y + m[2][3] * v.z + m[3][3] );
	vec3 r(0.0f);
	r.x = ( m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z + m[3][0] ) * fInvW;
	r.y = ( m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z + m[3][1] ) * fInvW;
	r.z = ( m[0][2] * v.x + m[1][2] * v.y + m[2][2] * v.z + m[3][2] ) * fInvW;
	return r;
}

inline vec4 mat4::mul(const vec4& v )const
{
	SLMATH_VEC_ASSERT( v.check() );
	SLMATH_VEC_ASSERT( this->check() );
	return v4()[0]*v.x + v4()[1]*v.y + v4()[2]*v.z + v4()[3]*v.w;
}

inline void mat4::identify()
{
	*this = IDENTITY();
}

inline bool mat4::check()const
{
	return slm::check(&m[0][0], SIZE);
}

#ifdef SLMATH_AUTO_DX_CONVERSION
inline mat4& mat4::operator = (const D3DXMATRIX& dxmat)
{
	*this = mat4(dxmat.operator CONST FLOAT*());
	return *this;
}

inline mat4::operator D3DXMATRIX()const
{
	return D3DXMATRIX(&m[0][0]);
}
#endif // SLMATH_AUTO_DX_CONVERSION

inline bool check(const mat4& m)
{
	return m.check();
}

inline std::ostream& operator << (std::ostream& stream, const mat4& m)
{
	stream << "mat4("\
		<< "[" << m[0][0] << "," << m[0][1] << "," << m[0][2] << "," << m[0][3] << "]"\
		<< "[" << m[1][0] << "," << m[1][1] << "," << m[1][2] << "," << m[1][3] << "]"\
		<< "[" << m[2][0] << "," << m[2][1] << "," << m[2][2] << "," << m[2][3] << "]"\
		<< "[" << m[3][0] << "," << m[3][1] << "," << m[3][2] << "," << m[3][3] << "]"\
		<< ")";

	return stream;
}

inline std::wostream& operator << (std::wostream& stream, const mat4& m)
{
	stream << L"mat4("\
		<< L"[" << m[0][0] << L"," << m[0][1] << L"," << m[0][2] << L"," << m[0][3] << L"]"\
		<< L"[" << m[1][0] << L"," << m[1][1] << L"," << m[1][2] << L"," << m[1][3] << L"]"\
		<< L"[" << m[2][0] << L"," << m[2][1] << L"," << m[2][2] << L"," << m[2][3] << L"]"\
		<< L"[" << m[3][0] << L"," << m[3][1] << L"," << m[3][2] << L"," << m[3][3] << L"]"\
		<< L")";

	return stream;
}

inline mat4 operator * (float fv, const mat4& mat)
{
	return mat.mul(fv);
}

// This file is part of 'slm' C++ library. Copyright (C) 2009 Jani Kajala (kajala@gmail.com). See http://sourceforge.net/projects/slm/
